package RenderLayer;

import ModelLayer.Direction;
import ModelLayer.Game;
import ModelLayer.Room;
import ModelLayer.RoomCharacter;
import ModelLayer.Tile;
import ServiceLayer.XMLRoomParser;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;

import com.example.genericrpg_android.GameView;

public class RoomView extends View {
	private int leftBT, rightBT, bottBT, topBT;   	// Border Tiles
	private int x1, x2, y1, y2, dx1,dx2,dy1,dy2;	// image and destination (x,y)'s
	private int factorX, factorY, xBound, yBound; 
	private int spriteWidth, currentSprite;			
	private int W, H, tW, tH, alpha;				// Width and Height (view, tiles)
	private int playLayer, intLayer;
	private XMLRoomParser currentMap;
	private Bitmap playerSprites;
	private Bitmap[] tileSets;
	private int[] spriteX, spriteY;
	private int[][][] map;
	private Paint blackPaint;
	private Rect tileSrc = new Rect();
	private Rect tileDst= new Rect();
	private Rect playDst= new Rect();
	private Rect playSrc= new Rect();
	private double zoom;
	private RoomCharacter mCharacter; 
	private Game mModel;
	private Room room;
	private Paint redPaint;
	private Paint whitePaint;
	private double growText;
	
	public RoomView(Game model, GameView view){
		mModel = model;
		room = mModel.getCurrentRoom();
		currentMap = room.getRoomParser();
		tW = currentMap.getTileWidth(); 
		tH = currentMap.getTileHeight();
		playLayer = currentMap.getPlayerLayer(); 
		intLayer = currentMap.getInteractionLayer();
		Context activity = view.getContext();
		H = view.getHeight();  W = view.getWidth();
		try {
			playerSprites = BitmapFactory.decodeStream(activity.getAssets().open("sprites/placeHolderSprites.png"));
			
			spriteX = new int[12];
			spriteY = new int[12];
			spriteWidth = 34;
			
			for (int y = 0, count = 0; y < 4; y++)
				for (int x = 0; x < 3; x++) {
					spriteX[count] = x * 20;
					spriteY[count] = y * 26;
					count++;	
				}
			alpha = 0;
		} catch (Exception e) {
			e.printStackTrace();
		}
		currentSprite = 7;
		zoom = H * 1.5 / GameView.VIEW_HEIGHT;
		if(W < 500)
			zoom = 1.2;
		redPaint = new Paint(); 
		redPaint.setColor(Color.RED);
		redPaint.setTextSize(W/30);
		blackPaint = new Paint();
		blackPaint.setColor(Color.BLACK);
		blackPaint.setTextSize(H/4);
		whitePaint = new Paint();
		whitePaint.setTextSize(W/30);
		whitePaint.setColor(Color.WHITE);
		factorX = (int)((W / 2)/((tW * zoom)) + 2);
		factorY = (int) ((H / 2)/ ((tH * zoom)) + 2); 
	}
	
	@Override
	public void render(Canvas g, GameView root) {

		mCharacter = mModel.getCharacter();
		room = mModel.getCurrentRoom();
		currentMap = room.getRoomParser();
		map = currentMap.getLayeredMap();
		tileSets = currentMap.getTileSets();
		
		switch(mCharacter.getFacingDirection()){
		case Direction.RIGHT:
			if((mCharacter.tilePosition.x*32) - mCharacter.pixelPosition.x < 16){
				currentSprite = 4;
			} else {
				if(mCharacter.firstX)	currentSprite = 3; 
				else					currentSprite = 5; 
			}
			break;
		case Direction.LEFT:
			if(mCharacter.pixelPosition.x - (mCharacter.tilePosition.x*32) < 16){
				currentSprite = 10;
			}  else {
				if(mCharacter.firstX)	currentSprite = 9; 
				else					currentSprite = 11; 
			}
			break;
		case Direction.UP:
			if(mCharacter.pixelPosition.y - (mCharacter.tilePosition.y*32) < 16){
				currentSprite = 1;
			} else {
				if(mCharacter.firstY)	currentSprite = 0; 
				else					currentSprite = 2; 
			}
			break;
		case Direction.DOWN:
			if((mCharacter.tilePosition.y*32) - mCharacter.pixelPosition.y < 16){
				currentSprite = 7;
			} else {
				if(mCharacter.firstY)	currentSprite = 6; 
				else					currentSprite = 8; 
			}
			break;
		}
		
	
	    /*
		 * Bounds the drawn tiles to only the ones being shown on the JPanel.
		 * Previously, the entire map would be drawn, despite only a portion of
		 * it being shown on the screen, which slowed down performance
		 * considerably.
		 */
		leftBT = mCharacter.tilePosition.x - factorX;
		rightBT = mCharacter.tilePosition.x + factorX;
		topBT = mCharacter.tilePosition.y - factorY;
		bottBT = mCharacter.tilePosition.y + factorY;

		if (leftBT >= 0)	xBound = leftBT;
		else				xBound = 0;
		
		if (topBT >= 0)		yBound = topBT;
		else				yBound = 0;

		for (int z = 0; z < currentMap.getLayerNum(); z++) {
			/* Skips drawing if the current layer is the collision layer. */
			if (z == playLayer) {
				playSrc.set(spriteX[currentSprite], 
						spriteY[currentSprite],
						spriteX[currentSprite] + 20,
						spriteY[currentSprite] + 26);
				playDst.set( (int) ((W / 2) - ((spriteWidth / 2) * zoom)),
						(int) ((H / 2) - (38 * zoom)),
						(int) ((W / 2) + ((spriteWidth / 2) * zoom)),
						(int) ((H / 2) + (8 * zoom)) );
				
				g.drawBitmap(playerSprites,playSrc, playDst, null);

			} else if (z != currentMap.getCollisionLayer() && z != intLayer) {
				for (int y = yBound; y <= bottBT && y < currentMap.getRoomHeight(); y++) {
					for (int x = xBound; x <= rightBT && x < currentMap.getRoomWidth(); x++) {
						int index = map[z][y][x];
						
						if (index != -1) {	
							x1 = (int) ((((x * tW) - mCharacter.pixelPosition.x) * zoom) + ((W / 2) - (tW * zoom / 2)));
							y1 = (int) ((((y * tH) - mCharacter.pixelPosition.y) * zoom) + ((H / 2) - (tH * zoom / 2)));
							x2 = (int) (((((x * tW) - mCharacter.pixelPosition.x) * zoom) + (tW * zoom)) + ((W / 2) - (tW * zoom / 2)));
							y2 = (int) (((((y * tH) - mCharacter.pixelPosition.y) * zoom) + (tH * zoom)) + ((H / 2) - (tH * zoom / 2)));

							tileDst.set(x1, y1, x2, y2);
							
							int tileSetUsed = -1;
							int tileSetOffset = 0;
							for (int i = 0; i < tileSets.length; i++) {
								if (index >= currentMap.getTileSetFirstIds()[i]) {
									tileSetUsed++;
									tileSetOffset = currentMap.getTileSetFirstIds()[i];
								}
							}
							index -= tileSetOffset;

							int yOffset = 0;
							while (index > (tileSets[tileSetUsed].getWidth() / tW) - 1) {
								yOffset++;
								index = index- (tileSets[tileSetUsed].getWidth() / tW);
							}

							dx1 = index * tW;
							dy1 = yOffset * tH;
							dx2 = (index * tW)+ tW;
							dy2 = (yOffset * tH)+ tH;

							tileSrc.set(dx1, dy1, dx2, dy2); 
							g.drawBitmap(tileSets[tileSetUsed],tileSrc, tileDst , null);
						}
					}
				}
			}
		}
		if (!room.timeOut)
			paintTimer(g);
		
		Tile t = room.getCurrentTile(mCharacter.tilePosition);
		if (t.getValue() == Tile.DOOR_TILE){
			if (alpha<=253)
				alpha += 3;
			g.drawARGB(alpha, 0, 0, 0);
		}
		else if(t.getValue() == Tile.END_TILE && !room.restarting){
			if (alpha<=253)
				alpha += 2;
			g.drawARGB(alpha, 210, 210, 210);
			g.drawText("Way to Go!", W/6, H/2, blackPaint);
			g.drawText("your score: "+room.score, W/3, H*2/3, redPaint);
		}
		else if (room.restarting){
			if (alpha<=253)
				alpha += 3;
			g.drawARGB(alpha, 210, 210, 210);
			g.drawText("Restarting", W/6, H/2, blackPaint);
		}
		else if (room.timeOut){
			if (alpha<=253)
				alpha += 3;
			growText -= .4;
			redPaint.setTextSize((int)(W/growText));
			g.drawARGB(alpha, 210, 210, 210);
			g.drawText("Time Out", W/6, H/2, redPaint);
		}else {
			alpha = 0;
			growText = 30;
			redPaint.setTextSize((int)(W/growText));
		}
	}

	private void paintTimer(Canvas g){
		if (room.time < 50 &&  (room.time)%2 == 0){
			g.drawText("TIME: "+room.time/10, W/15, H/10, redPaint);
		}else {
			g.drawText("TIME: "+room.time/10, W/15, H/10, whitePaint);
		}
	}
}



